package com.miya.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.miya.constant.MiyaConstant;
import com.miya.entity.MiyaResponse;
import com.miya.entity.PageRequest;
import com.miya.entity.PageResult;
import com.miya.entity.system.*;
import com.miya.handler.Assert;
import com.miya.system.mapper.UserMapper;
import com.miya.system.model.AddUserDTO;
import com.miya.system.model.EditUserDTO;
import com.miya.system.service.*;
import com.miya.utils.PageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author Caixiaowei
 * @since 2020-05-14
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, SystemUser> implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private IDeptService deptService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IDeptUserService deptUserService;
    @Autowired
    private IUserRoleService userRoleService;

    /**
     * @param request
     * @param user
     * @throws
     * @title 分页查找用户信息
     * @description
     * @author Caixiaowei
     * @updateTime 2020/5/14 10:44
     */
    @Override
    public PageResult<SystemUser> list(SystemUser user, PageRequest request) {
        PageResult<SystemUser> pageResult = PageUtil.queryByPage(request, page -> userMapper.findUserDetailPage(page, user));
        return pageResult;
    }

    @Override
    public SystemUser findByName(String username) {
        return this.lambdaQuery()
                .eq(SystemUser::getUsername, username)
                .last(MiyaConstant.SQL_LIMIT_ONE)
                .one();
    }

    /**
     * 添加
     *
     * @param dto dto
     * @return {@link MiyaResponse}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MiyaResponse add(AddUserDTO dto) {
        // 检查用户数据
        this.checkAddUserData(dto);
        SystemUser systemUser = new SystemUser();
        BeanUtil.copyProperties(dto, systemUser, CopyOptions.create().ignoreNullValue());
        this.save(systemUser);

        // 用户部门信息入库
        DeptUser deptUser = new DeptUser(systemUser.getId(), dto.getDeptId());
        deptUserService.save(deptUser);

        // 用户角色信息入库
        List<UserRole> userRoles = dto.getRoleIds().stream().map(x -> {
            return new UserRole(systemUser.getId(), x);
        }).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(userRoles)) {
            userRoleService.saveBatch(userRoles);
        }
        return MiyaResponse.success();
    }

    /**
     * 修改用户
     *
     * @param dto dto
     * @return {@link MiyaResponse}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MiyaResponse edit(EditUserDTO dto) {
        SystemUser systemUser = this.getById(dto.getId());
        Assert.isNull(systemUser, "用户不存在!");
        this.checkEditUserData(dto);
        BeanUtil.copyProperties(dto, systemUser.getClass(), CopyOptions.create().ignoreNullValue());

        // 编辑入库
        this.updateById(systemUser);

        // 部门更新
        deptUserService.deleteByUserIds(Arrays.asList(dto.getId()));
        DeptUser deptUser = new DeptUser(systemUser.getId(), dto.getDeptId());
        deptUserService.save(deptUser);

        // 角色更新
        userRoleService.deleteUserRolesByUserId(Arrays.asList(dto.getId()));
        List<UserRole> userRoles = dto.getRoleIds().stream().map(x -> {
            return new UserRole(systemUser.getId(), x);
        }).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(userRoles)) {
            userRoleService.saveBatch(userRoles);
        }
        return MiyaResponse.success();
    }

    /**
     * 检查编辑用户数据
     *
     * @param dto dto
     */
    private void checkEditUserData(EditUserDTO dto) {
        String username = dto.getUsername();
        Long deptId = dto.getDeptId();
        List<Long> roleIds = dto.getRoleIds();

        SystemUser systemUser = this.findByName(username);
        Assert.state(systemUser != null && !dto.getId().equals(systemUser.getId()), "用户名已被占用");

        this.checkDeptAndRoleState(deptId, roleIds);
    }


    /**
     * 检查添加用户数据
     *
     * @param dto dto
     */
    private void checkAddUserData(AddUserDTO dto) {
        String username = dto.getUsername();
        Long deptId = dto.getDeptId();
        List<Long> roleIds = dto.getRoleIds();

        SystemUser systemUser = this.findByName(username);
        Assert.nonNull(systemUser, "用户名已被占用!");

        this.checkDeptAndRoleState(deptId, roleIds);
    }

    private void checkDeptAndRoleState(Long deptId, List<Long> roleIds) {
        Dept dept = deptService.getById(deptId);
        Assert.isNull(dept, "部门不存在");

        for (Long roleId : roleIds) {
            Role role = roleService.getById(roleId);
            Assert.isNull(role, "角色不存在");
        }

    }
}
